package com.yanfan.iot.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yanfan.common.annotation.CacheBatch;
import com.yanfan.common.annotation.CacheBatchEvict;
import com.yanfan.common.core.domain.AjaxResult;
import com.yanfan.common.core.redis.RedisCache;
import com.yanfan.common.core.redis.RedisKeyBuilder;
import com.yanfan.common.exception.job.TaskException;
import com.yanfan.common.utils.DateUtils;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.common.utils.StringUtils;
import com.yanfan.iot.cache.ITSLCache;
import com.yanfan.iot.cache.ITSLValueCache;
import com.yanfan.iot.domain.*;
import com.yanfan.iot.domain.vo.CommonVo;
import com.yanfan.iot.mapper.*;
import com.yanfan.iot.model.*;
import com.yanfan.iot.model.ThingsModelItem.EnumItem;
import com.yanfan.iot.model.dto.ThingsModelDTO;
import com.yanfan.iot.service.IProductService;
import com.yanfan.iot.service.IThingsModelService;
import com.yanfan.iot.service.IThingsModelTemplateService;
import com.yanfan.quartz.domain.SysJob;
import com.yanfan.quartz.service.ISysJobService;
import org.apache.commons.collections4.CollectionUtils;
import org.quartz.SchedulerException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;import org.springframework.lang.Nullable;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.math.BigDecimal;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.yanfan.common.utils.SecurityUtils.getLoginUser;

/**
 * 产品Service业务层处理
 *
 * @author kerwincui
 * @date 2021-12-16
 */
@Service
public class ProductServiceImpl implements IProductService {

    @Autowired
    private ThingsModelServiceImpl thingsModelService;

    @Resource
    private ProductMapper productMapper;

    @Autowired
    private ProductAuthorizeMapper productAuthorizeMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ToolServiceImpl toolService;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceTemplateMapper templateMapper;

    @Autowired
    private IThingsModelTemplateService modelTemplateService;
    @Resource
    private SceneDeviceMapper sceneDeviceMapper;
    @Resource
    private ITSLValueCache thingModelCache;
    @Resource
    private ITSLCache itslCache;

    // 产品默认账号
    @Value("${spring.mqtt.prod-def-user:yanfan}")
    private String prodDefUsername;

    @Autowired
    private ISysJobService sysJobService;



    /**
     * 查询产品
     *
     * @param productId 产品主键
     * @return 产品
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #productId", unless = "#result == null")
    @Override
    public Product selectProductByProductId(Long productId) {
        Product product = productMapper.selectProductByProductId(productId);
        if (Objects.nonNull(product) && Objects.equals(product.getTransport(),"HTTP")) {
            Integer httptype = product.getHttptype();
            userParmas userParmas = new userParmas();
            if (httptype==1) {
                userParmas.setUser(product.getUsername());
                userParmas.setPassword(product.getUserpassword());
                userParmas.setIsLogin(true);
                userParmas.setUrl(product.getUrl());
            }else {
                userParmas.setIsLogin(false);
            }
            product.setUserParmas(userParmas);
        }
        return product;
    }

    /**
     * 查询产品列表
     *
     * @param product 产品
     * @return 产品
     */
    @Override
    public List<Product> selectProductList(Product product) {
        List<Product> productList = productMapper.selectProductList(product);
        // 组态不是所有人都买了，故单独查询组态信息
        List<String> guidList = productList
                .stream()
                .map(Product::getGuid)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(guidList)) {
            List<Product> scadaList = productMapper.selectListScadaIdByGuidS(guidList);
            Map<String, Long> map = scadaList.stream().collect(Collectors.toMap(Product::getGuid, Product::getScadaId));
            for (Product product1 : productList) {
                Long scadaId = map.get(product1.getGuid());
                product1.setScadaId(scadaId);
            }
        }
        return productList;
    }

    /**
     * 查询产品简短列表
     *
     * @return 产品
     */
    @Override
    public List<IdAndName> selectProductShortList(Product product) {
        return productMapper.selectProductShortList(product);
    }

    /**
     * 新增产品
     *
     * @param product 产品
     * @return 结果
     */
    @CachePut(value = "product", key = "'selectProductByProductId_' + #root.args[0].productId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Product insertProduct(Product product) {
        // mqtt账号密码
        if (product.getMqttAccount() == null || product.getMqttAccount().equals("")) {
            product.setMqttAccount(prodDefUsername);
        }
        if (product.getMqttPassword() == null || product.getMqttPassword().equals("")) {
            product.setMqttPassword("P" + toolService.getStringRandom(15));
        }
        if (product.getMqttSecret() == null || product.getMqttSecret().equals("")) {
            product.setMqttSecret("K" + toolService.getStringRandom(15));
        }
        product.setStatus(product.getStatus() == null ? 1 : product.getStatus());
        product.setCreateTime(DateUtils.getNowDate());
        if("HTTP".equals(product.getTransport())){
            List<HttpParam> headers = product.getHeadersList();
            product.setHeaders(JSONArray.toJSONString(headers));
            List<HttpParam> paramsDataList = product.getParamsDataList();
            product.setParamsData(JSONArray.toJSONString(paramsDataList));
            userParmas userParmas = product.getUserParmas();
            product.setUsername(userParmas.getUser());
            product.setUserpassword(userParmas.getPassword());
            product.setHttpurl(userParmas.getUrl());
            //需要获取登录key
            if(userParmas.getIsLogin()){
                product.setHttptype(1);
                String key = httplogin(userParmas.getUser(),userParmas.getPassword(),userParmas.getUrl());
                if (key.equals("请求参数失败")) {
                    System.out.println("请求key参数失败");
                    return null;
                }
                product.setUserkey(key);
            }
            else{
                product.setHttptype(0);
            }
        }


        int i = productMapper.insertProduct(product);

        //新增HTTP传输协议产品后创建定时任务
        if("HTTP".equals(product.getTransport()) && i > 0){
            SysJob sysJob = new SysJob();
            sysJob.setJobId(product.getProductId());
            sysJob.setJobName(product.getProductName()+"-http请求定时任务");
            sysJob.setCronExpression(product.getCronExpression());
            sysJob.setInvokeTarget("iotHttpClient.ProductJob("+product.getProductId() +  "L)");
            sysJob.setMisfirePolicy("2");
            sysJob.setStatus("0");
            sysJob.setConcurrent("0");
            sysJob.setJobGroup("SYSTEM");
            sysJob.setCreateBy(getLoginUser().getUsername());
            try {
                sysJobService.insertJob(sysJob);
            } catch (SchedulerException e) {
                e.printStackTrace();
            } catch (TaskException e) {
                e.printStackTrace();
            }
        }
        if("SNMP".equals(product.getTransport()) && i>0 ) {
            SysJob sysJob = new SysJob();
            sysJob.setJobId(product.getProductId());
            sysJob.setJobName(product.getProductName()+"-snmp定时任务");
            sysJob.setCronExpression(product.getCronExpression());
            sysJob.setInvokeTarget("snmpJob.snmpProductJob("+product.getProductId() +  "L)");
            sysJob.setMisfirePolicy("2");
            sysJob.setStatus("0");
            sysJob.setConcurrent("0");
            sysJob.setJobGroup("SYSTEM");
            sysJob.setCreateBy(getLoginUser().getUsername());
            try {
                sysJobService.insertJob(sysJob);
            } catch (SchedulerException e) {
                e.printStackTrace();
            } catch (TaskException e) {
                e.printStackTrace();
            }
        }

        /*如果产品属于modbus协议（云端轮询）需要记录变量模板与产品关系*/
        if (product.getTemplateId() != null) {
            DeviceTemplate template = new DeviceTemplate();
            template.setProductId(product.getProductId());
            template.setTemplateId(product.getTemplateId());
            templateMapper.insertDeviceTemplate(template);

            //将模板物模型导入到物模型表
            List<ThingsModelTemplate> thingsModelTemplates = modelTemplateService.selectAllByTemplateId(product.getTemplateId());
            Long[] ids = thingsModelTemplates.stream().map(ThingsModelTemplate::getTemplateId).toArray(Long[]::new);
            ImportThingsModelInput input = new ImportThingsModelInput();
            input.setTemplateIds(ids);
            input.setProductId(product.getProductId());
            input.setProductName(product.getProductName());
            thingsModelService.importByTemplateIds(input);
        }
        return product;
    }


    //登录获取key的接口
    @Override
    public String httplogin(String username, String password,String rul){
        String token = null;
        //连接
        HttpURLConnection connection = null;
        OutputStream os = null;
        InputStream is = null;
        BufferedReader br = null;
        try {
            //创建连接对象
            URL url = new URL(rul);
            //创建连接
            connection = (HttpURLConnection) url.openConnection();
            //设置请求方法
            connection.setRequestMethod("POST");
            //设置连接超时时间
            connection.setConnectTimeout(15000);
            //设置读取超时时间
            connection.setReadTimeout(15000);
            //DoOutput设置是否向httpUrlConnection输出，DoInput设置是否从httpUrlConnection读入，此外发送post请求必须设置这两个
            //设置是否可读取
            connection.setDoOutput(true);
            connection.setDoInput(true);
            //设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            //数据请求
            // 拼装参数
            String param = "{\"user_name\":\"" + username + "\",\"user_password\":\"" + password + "\"}";

            // 设置参数
            os = connection.getOutputStream();
            // 发送参数
            os.write(param.getBytes(StandardCharsets.UTF_8));
            os.flush();
            // 获取响应码
            int responseCode = connection.getResponseCode();
            System.out.println("响应码: " + responseCode);            //读取响应
            // 读取响应
            if (responseCode == HttpURLConnection.HTTP_OK) {
                InputStream iss = connection.getInputStream();
                br = new BufferedReader(new InputStreamReader(iss, StandardCharsets.UTF_8));

                StringBuilder responseData = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    responseData.append(line);
                }

                // 将响应数据解析为JSON对象
                JSONObject jsonResponse = JSONObject.parseObject(responseData.toString());
                // 假设你需要的数据在JSON对象的"data"键中
                String data = jsonResponse.getString("result_data");
                //获取token值
                JSONObject jsonResponsedata = JSONObject.parseObject(data);
                token = jsonResponsedata.getString("token");
            } else {
                System.out.println("请求失败");
                return "请求失败";
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
                if (br != null) {
                    br.close();
                }
                if (connection != null) {
                    connection.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return token;
    }

    @Override
    public List<String> getcode() {
        return productMapper.getcode();
    }

    /**
     * 修改产品
     *
     * @param product 产品
     * @return 结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "deviceMqttConnCache",  allEntries = true),
    })
    @CacheBatch(batchEvict = {
            @CacheBatchEvict(cacheNames = "product", key = "'selectProductByProductId_' + #product.productId"),
            @CacheBatchEvict(cacheNames = "device", key = "'selectProductAuthenticate_*_' + #product.productId"),
    })
    @Transactional
    public int updateProduct(Product product) {
        product.setUpdateTime(DateUtils.getNowDate());
        //修改HTTP传输协议产品
        if("HTTP".equals(product.getTransport())){
            userParmas userParmas = product.getUserParmas();
            product.setUsername(userParmas.getUser());
            product.setUserpassword(userParmas.getPassword());
            product.setHttpurl(userParmas.getUrl());
            //需要获取登录key
            if(userParmas.getIsLogin()){
                product.setHttptype(1);
                String key = httplogin(userParmas.getUser(),userParmas.getPassword(),userParmas.getUrl());
                if (key.equals("请求参数失败")) {
                    return 0;
                }
                product.setUserkey(key);
            }
            else{
                product.setHttptype(0);
            }
            List<HttpParam> headers = product.getHeadersList();
            product.setHeaders(JSONArray.toJSONString(headers));
            List<HttpParam> paramsDataList = product.getParamsDataList();
            product.setParamsData(JSONArray.toJSONString(paramsDataList));

            //修改定时任务 cron表达式
            SysJob sysJob = new SysJob();
            sysJob.setJobId(product.getProductId());
            sysJob.setCronExpression(product.getCronExpression());
            sysJob.setStatus("1");

            try {
                sysJobService.updateJob(sysJob);
            } catch (SchedulerException e) {
                e.printStackTrace();
            } catch (TaskException e) {
                e.printStackTrace();
            }
        }

        //修改SNMP传输协议产品
        if("SNMP".equals(product.getTransport())){
            //修改定时任务 cron表达式
            SysJob sysJob = sysJobService.selectJobById(product.getProductId());
            sysJob.setCronExpression(product.getCronExpression());
            try {
                sysJobService.updateJob(sysJob);
            } catch (SchedulerException e) {
                e.printStackTrace();
            } catch (TaskException e) {
                e.printStackTrace();
            }
        }
        return productMapper.updateProduct(product);
    }

    /**
     * 获取产品下面的设备数量
     *
     * @param productId 产品ID
     * @return 结果
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #productId", unless = "#result == null")
    @Override
    public int selectDeviceCountByProductId(Long productId) {
        return deviceMapper.selectDeviceCountByProductId(productId);
    }

    /**
     * 更新产品状态,1-未发布，2-已发布
     *
     * @param model
     * @return 结果
     */
    @Override
    @Transactional
    @CacheEvict(value = "product", allEntries = true)
    public AjaxResult changeProductStatus(ChangeProductStatusModel model) {
        if (model.getStatus() != 1 && model.getStatus() != 2) {
            return AjaxResult.error("状态更新失败,状态值有误");
        }
        if (model.getStatus() == 2) {
            // 不需要一定要有物模型才可以发布
            updateDeviceStatusByProductIdAsync(model.getProductId());
            //更新物模型缓存
            itslCache.setCacheThingsModelByProductId(model.getProductId());
        }
        if (productMapper.changeProductStatus(model) > 0) {
            return AjaxResult.success("操作成功");
        }
        return AjaxResult.error("状态更新失败");
    }

    /***
     * 更新产品下所有设备的物模型值
     * @param productId
     */
    @Async
    public void updateDeviceStatusByProductIdAsync(Long productId) {
        List<String> deviceNumbers = deviceMapper.selectSerialNumberByProductId(productId);
        deviceNumbers.forEach(x -> {
            // 缓存新的物模型值
            thingModelCache.addCacheDeviceStatus(productId, x);
        });
    }

    /**
     * 批量删除产品
     *
     * @param productIds 需要删除的产品主键
     * @return 结果
     */
    @CacheEvict(value = "product", allEntries = true)
    @Override
    @Transactional
    public AjaxResult deleteProductByProductIds(Long[] productIds) {
        // 删除物模型JSON缓存
        for (int i = 0; i < productIds.length; i++) {
            String key = RedisKeyBuilder.buildTSLCacheKey(productIds[i]);
            redisCache.deleteObject(key);
        }
        // 产品下不能有固件
        int firmwareCount = productMapper.firmwareCountInProducts(productIds);
        if (firmwareCount > 0) {
            return AjaxResult.error("删除失败，请先删除对应产品下的固件");
        }
        // 产品下不能有设备
        int deviceCount = productMapper.deviceCountInProducts(productIds);
        if (deviceCount > 0) {
            return AjaxResult.error("删除失败，请先删除对应产品下的设备");
        }
        // 产品下不能有场景联动
        List<SceneDeviceBindVO> sceneDeviceBindVOList = sceneDeviceMapper.listSceneProductBind(productIds);
        if (CollectionUtils.isNotEmpty(sceneDeviceBindVOList)) {
            String sceneNames = sceneDeviceBindVOList
                    .stream()
                    .map(SceneDeviceBindVO::getSceneName)
                    .collect(Collectors.joining("，"));
            return AjaxResult.error("删除失败，请先修改或删除对应产品下的场景联动：" + sceneNames);
        }
        // 删除产品物模型
        productMapper.deleteProductThingsModelByProductIds(productIds);
        // 删除产品的授权码
        productAuthorizeMapper.deleteProductAuthorizeByProductIds(productIds);


        //删除产品的定时任务
        List<Long> productJobIdList = new ArrayList<>();
        for (Long productId : productIds) {
            Product product = this.selectProductByProductId(productId);
            if("HTTP".equals(product.getTransport()) || "SNMP".equals(product.getTransport())){
                productJobIdList.add(productId);
            }
        }
        // HTTP协议的产品id
        Long[] productJobIds = productJobIdList.toArray(new Long[productJobIdList.size()]);

        if(productJobIds.length > 0){
            try {
                sysJobService.deleteJobByIds(productJobIds);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

        // 删除产品
        if (productMapper.deleteProductByProductIds(productIds) > 0) {
            return AjaxResult.success("删除成功");
        }
        return AjaxResult.error("删除失败");
    }


    /**
     * 删除产品信息
     *
     * @param productId 产品主键
     * @return 结果
     */
    @CacheEvict(value = "product", allEntries = true)
    @Override
    @Transactional
    public int deleteProductByProductId(Long productId) {
        // 删除物模型JSON缓存
        redisCache.deleteObject(RedisKeyBuilder.buildTSLCacheKey(productId));
        //删除HTTP协议产品的定时任务
        Product product = this.selectProductByProductId(productId);
        if("HTTP".equals(product.getTransport()) || "SNMP".equals(product.getTransport())){
            SysJob sysJob = new SysJob();
            sysJob.setJobId(product.getProductId());
            try {
                sysJobService.deleteJob(sysJob);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }

        return productMapper.deleteProductByProductId(productId);
    }

    /**
     * 根据设备编号查询产品信息
     *
     * @param serialNumber 设备编号
     * @return 结果
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #serialNumber", unless = "#result == null")
    @Override
    public Product getProductBySerialNumber(String serialNumber) {
        return productMapper.getProductBySerialNumber(serialNumber);
    }

    /**
     * 根据设备编号查询协议编号
     *
     * @param serialNumber 设备编号
     * @return 协议编号
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #serialNumber", unless = "#result == null")
    @Override
    public ProductCode getProtocolBySerialNumber(String serialNumber) {
        return productMapper.getProtocolBySerialNumber(serialNumber);
    }

    /**
     * 根据产品id获取协议编号
     *
     * @param productId 产品id
     * @return 协议编号
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #productId", unless = "#result == null")
    @Override
    public String getProtocolByProductId(Long productId) {
        return productMapper.getProtocolByProductId(productId);
    }


    /**
     * 根据模板id查询所有使用的产品
     *
     * @param templeId 模板id
     * @return
     */
    @Cacheable(value = "product", key = "#root.methodName + '_' + #templeId", unless = "#result == null")
    @Override
    public List<Product> selectByTempleId(Long templeId) {
        return productMapper.selectByTempleId(templeId);
    }

    @Override
    public String selectImgUrlByProductId(Long productId) {
        return productMapper.selectImgUrlByProductId(productId);
    }

    @Override
    public List<Product> selectTerminalUserProduct(Product product) {
        return productMapper.selectTerminalUserProduct(product);
    }

    /**
     * 根据产品id获取关联组态guid
     *
     * @param productId
     * @return guid
     */
    @Override
    public String selectGuidByProductId(Long productId) {
        return productMapper.selectGuidByProductId(productId);
    }

    /**
     * 查询产品统计
     *
     * @return 结果
     */
    @Override
    public CommonVo selectCount() {
        return productMapper.selectCount();
    }

    @Override
    public AjaxResult insertproducts(List<Product> list) {

        //由于批量插入，需要设置用户ID和用户名，所以需要循环插入
        //获取当前登录用户ID
        Long userId = getLoginUser().getUserId();
        //获取当前登录用户名
        String username = getLoginUser().getUsername();
        //设置用户ID和用户名
        List<Product> products = list.stream()
                .peek(template -> template.setTenantId(userId)) // 设置用户 ID
                .peek(template -> template.setTenantName(username)) // 设置用户名
                .peek(template -> template.setCreateTime(new Date())) // 设置创建时间
                .collect(Collectors.toList());


        AtomicInteger count = new AtomicInteger();
        //循环插入表格中数据
        for (Product product : products) {

            // 判断mqtt账号没有就使用默认值
            if (product.getMqttAccount() == null || product.getMqttAccount().equals("")) {
                product.setMqttAccount(prodDefUsername);
            }
            // 判断mqtt密码没有则生成
            if (product.getMqttPassword() == null || product.getMqttPassword().equals("")) {
                product.setMqttPassword("P" + toolService.getStringRandom(15));
            }
            // 判断mqtt秘钥没有则生成
            if (product.getMqttSecret() == null || product.getMqttSecret().equals("")) {
                product.setMqttSecret("K" + toolService.getStringRandom(15));
            }

            // 判断状态是否为空，为空则设置为1，表示未发布
            product.setStatus(product.getStatus() == null ? 2 : product.getStatus());

            product.setProtocolCode("JSON");
            product.setTransport("MQTT");
            //首先判断是否有重复的产品，重复返回则修改产品信息

            //根据id查询产品是否存在
            if (productMapper.selectByProductId(product.getProductId()) != null) {

                //修改产品信息
                productMapper.updateProduct(product);

                //获取所有设备信息
                Device device = deviceMapper.selectShortDeviceBySerialNumber(product.getSerialNumber());

                //设备编号是否重复，重复则修改设备信息
                if (device != null) {

                    //表格内信息和数据库信息的产品id是否一致，如果不一致则不修改，一致则修改
                    if (device.getProductId().equals(product.getProductId())) {
                        //修改设备信息
                        deviceMapper.updateDevice(deviceImport(product));

                    } else {
                        //修改设备信息，设备编号唯一，不同产品下也不能重复
                        return AjaxResult.error("设备编号"+ device.getSerialNumber() +"重复，且不属于同一产品，请检查");

                    }

                    //判断物模型产品下唯一标识是否重复，重复则修改，不重复则插入
                    //获取物模型数据并转为json
                    ThingsModel thingsModel = thingsModelImport(product);

                    //获取产品下物模型数量
                    List<ThingsModelDTO> thingsModelDTOS = productMapper.selectModelByProductId(product.getProductId());

                    //产品物模型为空则直接插入
                    if (thingsModelDTOS.size() == 0) {
                        thingsModelService.insertThingsModel(thingsModel);
                    } else {

                        int i = 0;
                        //循环判断产品下物模型是否重复
                        for (ThingsModelDTO thingsModelDTO : thingsModelDTOS) {
                            //判断物模型是否重复
                            if (thingsModelDTO.getIdentifier().equals(product.getIdentifier())) {
                                //修改物模型
                                i++;
                            }
                        }

                        //修改物模型
                        if (i != 0) {
                            thingsModelService.updateThingsModel(thingsModel);
                        } else {
                            //插入物模型
                            thingsModelService.insertThingsModel(thingsModel);
                        }
                    }


                } else {
                    //插入设备信息
                    deviceMapper.insertDevice(deviceImport(product));
                    //获取物模型数据并转为json
                    ThingsModel thingsModel = thingsModelImport(product);
                    //获取产品下物模型数量
                    List<ThingsModelDTO> thingsModelDTOS = productMapper.selectModelByProductId(product.getProductId());

                    //产品物模型为空则直接插入
                    if (thingsModelDTOS.size() == 0) {
                        thingsModelService.insertThingsModel(thingsModel);
                    } else {

                        int i = 0;
                        //循环判断产品下物模型是否重复
                        for (ThingsModelDTO thingsModelDTO : thingsModelDTOS) {
                            //判断物模型是否重复
                            if (thingsModelDTO.getIdentifier().equals(product.getIdentifier())) {
                                //修改物模型
                                i++;
                            }
                        }

                        //修改物模型
                        if (i != 0) {
                            thingsModelService.updateThingsModel(thingsModel);
                        } else {
                            //插入物模型
                            thingsModelService.insertThingsModel(thingsModel);
                        }
                    }

                }
            } else {

                //产品不重复则插入产品信息
                int i = productMapper.insertProduct(product);

                //插入设备信息
                //设备编号是否重复，重复则修改设备信息
                //获取设备信息
                Device device = deviceMapper.selectShortDeviceBySerialNumber(product.getSerialNumber());

                //查询到设备信息说明有重复
                if (device != null) {

                    //表格内信息和数据库信息的产品id是否一致，如果不一致则不修改，一致则修改
                    if (device.getProductId().equals(product.getProductId())) {
                        //修改设备信息
                        deviceMapper.updateDevice(deviceImport(product));

                        //获取物模型数据并转为json
                        ThingsModel thingsModel = thingsModelImport(product);
                        //插入物模型
                        thingsModelService.insertThingsModel(thingsModel);
                    } else {
                        //修改设备信息，设备编号唯一，不同产品下也不能重复
                        return AjaxResult.error("设备编号"+ device.getSerialNumber()+"重复，且不属于同一产品，请检查");

                    }

                } else {

                    //插入设备信息
                    deviceMapper.insertDevice(deviceImport(product));
                    //获取物模型数据并转为json
                    ThingsModel thingsModel = thingsModelImport(product);
                    //插入物模型
                    thingsModelService.insertThingsModel(thingsModel);

                }

            }

            count.addAndGet(1);
        }

        if (count.get() == products.size()) {
            return AjaxResult.success("导入成功");
        } else {
            return AjaxResult.error("导入失败");
        }
    }

    private Device deviceImport(Product product) {

        Device device = new Device();
        device.setSerialNumber(product.getSerialNumber());
        device.setProductId(product.getProductId());
        device.setDeviceName(product.getDeviceName());
        device.setProductName(product.getProductName());
        device.setDeviceType(product.getDeviceType());
        device.setCreateBy(product.getCreateBy());
        device.setCreateTime(new Date());
        device.setUpdateBy(product.getUpdateBy());
        device.setUpdateTime(new Date());
        device.setTenantName(product.getTenantName());
        device.setTenantId(product.getTenantId());

        //修改默认未激活状态
        device.setStatus(1);
        device.setFirmwareVersion(BigDecimal.valueOf(1));

        return device;
    }

    /**
     * 物模型转json
     *
     * @param product
     * @return
     */
    private ThingsModel thingsModelImport(Product product) {
        //处理表格内物模型
        ThingsModel thingsModel = new ThingsModel();
        thingsModel.setModelId(Long.valueOf(product.getModelId()));
        thingsModel.setModelName(product.getName());
        thingsModel.setProductId(product.getProductId());
        thingsModel.setProductName(product.getProductName());
        thingsModel.setTenantId(product.getTenantId());
        thingsModel.setTenantName(product.getTenantName());
        thingsModel.setType(Integer.valueOf(product.getType()));
        thingsModel.setIdentifier(product.getIdentifier());
        thingsModel.setDatatype(product.getDatatype());
        thingsModel.setUnit(product.getUnit());
        thingsModel.setIsChart(Integer.valueOf(product.getIsChart()));
        thingsModel.setIsMonitor(Integer.valueOf(product.getIsMonitor()));
        thingsModel.setCreateBy(product.getCreateBy());
        thingsModel.setCreateTime(new Date());
        thingsModel.setUpdateBy(product.getUpdateBy());
        //创建物模型json对象来接收数据
        ModelSpecs modelSpecs = new ModelSpecs();
        if (product.getDatatype().equals("bool")) {
            modelSpecs.setType("bool");
            modelSpecs.setTrueText(product.getTrueText());
            modelSpecs.setFalseText(product.getFalseText());
        } else if (product.getDatatype().equals("decimal") || product.getDatatype().equals("integer")) {
//            modelSpecs.setType(product.getDatatype());
            modelSpecs.setMax(product.getMax());
            modelSpecs.setUnit(product.getUnit());
            modelSpecs.setStep(product.getStep());
            modelSpecs.setMin(product.getMin());
        } else if (product.getDatatype().equals("string")) {
            modelSpecs.setType("string");
            modelSpecs.setMaxLength(product.getMaxLength());

        } else if (product.getDatatype().equals("enum")) {
            modelSpecs.setType("enum");
            if (product.getShowWay().equals("button")) {
                modelSpecs.setShowWay("button");
                EnumItem enumItem = new EnumItem();
                enumItem.setText(product.getText());
                enumItem.setValue(product.getValue());
                ArrayList<EnumItem> enumItems = new ArrayList<>();
                enumItems.add(enumItem);
                modelSpecs.setEnumList(enumItems);
            } else if (product.getShowWay().equals("select")) {
                modelSpecs.setShowWay("select");
                EnumItem enumItem = new EnumItem();
                enumItem.setText(product.getText());
                enumItem.setValue(product.getValue());
                ArrayList<EnumItem> enumItems = new ArrayList<>();
                enumItems.add(enumItem);
                modelSpecs.setEnumList(enumItems);
            }
        }

        //java对象转json字符串
        Object json = JSONObject.toJSON(modelSpecs);

        //将json字符串存入物模型
        thingsModel.setSpecs(json.toString());

        return thingsModel;
    }

    @Override
    public int updatekey(String key, Long productId) {
        return productMapper.updatekey(key, productId);
    }
}
